﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

// Ref : http://blogs.msdn.com/adamroot/pages/shell-style-drag-and-drop-in-net-wpf-and-winforms.aspx

namespace Streambolics.Hp41s.Gui
{
    /// <summary>
    ///     A control representing a magnetic card.
    /// </summary>
    /// <remarks><para>
    ///     The Magnetic Card control is a metaphor for persistent
    ///     storage.
    /// </para></remarks>

    public class MagneticCard : EngineControl
    {
        private bool _ReadOnly;
        private Data _Data;


        private static Bitmap _WritableCard;
        private static Bitmap _ReadOnlyCard;
        private static Bitmap _EmptyCard;

        #region Constructors

        public MagneticCard ()
        {
            Height = 60;
            Width = 371;
            Font = new Font ("Courier New", 12);
        }

        #endregion

        #region Painting

        public Bitmap WritableCard
        {
            get
            {
                if (_WritableCard == null)
                {
                    _WritableCard = Resources.MagneticCardImage;
                }
                return _WritableCard;
            }
        }

        public Bitmap ReadOnlyCard
        {
            get
            {
                if (_ReadOnlyCard == null)
                {
                    _ReadOnlyCard = Resources.MagneticCardImageRo;
                }
                return _ReadOnlyCard;
            }
        }

        public Bitmap EmptyCard
        {
            get
            {
                if (_EmptyCard == null)
                {
                    _EmptyCard = Resources.MagneticCardImageEmpty;
                }
                return _EmptyCard;
            }
        }
        protected override void OnPaint (PaintEventArgs e)
        {
            Rectangle r = DisplayRectangle;

            Bitmap b = Data == null ? EmptyCard : (_ReadOnly ? ReadOnlyCard : WritableCard);
            ImageAttributes attr = new ImageAttributes ();
            attr.SetColorKey (b.GetPixel (0, 0), b.GetPixel (0, 0));
            if (b != null)
            {
                e.Graphics.DrawImage (b, r, 0, 0, b.Width, b.Height, GraphicsUnit.Pixel, attr);
            }

            RenderText (e.Graphics, r);
        }

        protected override void OnTextChanged (EventArgs e)
        {
            base.OnTextChanged (e);
            Invalidate ();
        }

        #endregion

        [Description ("Whether the card is read only (a corner is shown cut)")]
        public bool ReadOnly
        {
            get
            {
                return _ReadOnly;
            }
            set
            {
                if (value != _ReadOnly)
                {
                    _ReadOnly = value;
                    DoReadOnlyChanged ();
                }
            }
        }

        [Description ("The attached data")]
        public Data Data
        {
            get
            {
                return _Data;
            }
            set
            {
                if (_Data != value)
                {
                    _Data = value;
                    DoDataChanged ();
                }
            }
        }

        #region DataChanged

        protected void DoDataChanged ()
        {
            OnDataChanged (EventArgs.Empty);
        }

        protected virtual void OnDataChanged (EventArgs e)
        {
            if (_Data == null)
            {
                Text = String.Empty;
            }
            else
            {
                Text = _Data.ToString ();
            }
        }

        #endregion

        #region ReadOnlyChanged

        protected void DoReadOnlyChanged ()
        {
            OnReadOnlyChanged (EventArgs.Empty);
        }

        protected virtual void OnReadOnlyChanged (EventArgs e)
        {
            Invalidate ();
        }

        #endregion

        #region Drag and Drop

        protected override void OnDragStart (Streambolics.Gui.DragStartEventArgs e)
        {
            base.OnDragStart (e);
            if (_Data != null)
            {
                e.DragObject = new DragData (Data, this);
            }
        }

        protected override void OnDragEnter (DragEventArgs aDragData)
        {
            base.OnDragEnter (aDragData);
            Data d = GetDragData<Data> (aDragData);

            if (!_ReadOnly && d != null)
            {
                aDragData.Effect = DragDropEffects.Copy;
            }
        }

        protected override void OnDragDrop (DragEventArgs aDragData)
        {
            base.OnDragDrop (aDragData);
            Data d = GetDragData<Data> (aDragData);

            if (!_ReadOnly && d != null)
            {
                Data = d;
            }
        }

        #endregion
    }
}
